package com.heyidlebooks.mgr;

import java.io.File;
import java.io.IOException;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;

import org.apache.log4j.Logger;
import org.apache.lucene.analysis.cjk.CJKAnalyzer;
import org.apache.lucene.document.DateTools;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import org.apache.lucene.index.CorruptIndexException;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.store.LockObtainFailedException;

import com.heyidlebooks.exception.LuceneException;
import com.heyidlebooks.model.Book;

public class Lucenev23Mgr {

	private Logger LOG = Logger.getLogger(Lucenev23Mgr.class);
	private IndexWriter writer;

	public Lucenev23Mgr(String indexDir) {
		File file = new File(indexDir);

		// the boolean true parameter means to create a new index everytime,
		// potentially overwriting any existing files there.
		try {
			writer = new IndexWriter(file, new CJKAnalyzer(), true);
			writer.setUseCompoundFile(false);
		} catch (CorruptIndexException e) {
			throw new LuceneException(e);
		} catch (LockObtainFailedException e) {
			throw new LuceneException(e);
		} catch (IOException e) {
			throw new LuceneException(e);
		}
	}
	
	public void reindex(List<Book> books) throws LuceneException {
		try {
			for (Book book : books) {
				Document doc = new Document();
				doc.add(new Field("key", book.getId().toString(),
						Field.Store.YES, Field.Index.NO));
				doc.add(new Field("id", book.getId().toString(),
						Field.Store.YES, Field.Index.UN_TOKENIZED));
				doc.add(new Field("ISBN", book.getIsbn(), Field.Store.YES,
						Field.Index.TOKENIZED));
				doc.add(new Field("ASIN", book.getASIN(), Field.Store.YES,
						Field.Index.TOKENIZED));
				doc.add(new Field("name", book.getTitle(), Field.Store.YES,
						Field.Index.TOKENIZED));
				doc.add(new Field("description", book.getDescription(),
						Field.Store.YES, Field.Index.TOKENIZED));
				doc.add(new Field("author", book.getAuthor(),
						Field.Store.YES, Field.Index.TOKENIZED));
				doc.add(new Field("publication_date",
						DateTools.dateToString(book.getPublicationDate(),
								DateTools.Resolution.MINUTE), Field.Store.YES,
						Field.Index.UN_TOKENIZED));
				doc.add(new Field("binding", book.getBinding(),
						Field.Store.YES, Field.Index.UN_TOKENIZED));
				doc.add(new Field("small_image", book.getSmallImage(),
						Field.Store.YES, Field.Index.UN_TOKENIZED));
				doc.add(new Field("medium_image", book.getMediumImage(),
						Field.Store.YES, Field.Index.UN_TOKENIZED));
				doc.add(new Field("large_image", book.getLargeImage(),
						Field.Store.YES, Field.Index.UN_TOKENIZED));
				try {
					doc.add(new Field("cities", getCities(book),
							Field.Store.YES, Field.Index.UN_TOKENIZED));
				} catch (SQLException e) {
					LOG.warn("Error when get user book cities, ID: " + book.getId() + ", Message: " + e.getMessage());
				}
				try {
					writer.addDocument(doc);
				} catch (CorruptIndexException e) {
					LOG.warn("Error when index book, ID: " + book.getId()
							+ ", Message: " + e.getMessage());
				} catch (IOException e) {
					LOG.warn("Error when index book, ID: " + book.getId()
							+ ", Message: " + e.getMessage());
				}

			}
		} finally {
			try {
				if (writer != null) {
					writer.optimize();
					writer.close();
				}
			} catch (CorruptIndexException e) {
				throw new LuceneException(e);
			} catch (IOException e) {
				throw new LuceneException(e);
			}
		}
	}

	/**
	 * Get city string, concatnated by comma.
	 * 
	 * @param book
	 * @return
	 * @throws SQLException
	 */
	private String getCities(Book book) throws SQLException {
		Connection conn = null;
		PreparedStatement pstmt = null;
		ResultSet rs = null;
		StringBuffer sb = new StringBuffer();
		try {
			conn = DatabaseConnectionMgr.getConnection();
			String sql = "SELECT u.view_location, u.location FROM user as u INNER JOIN user_book AS ub ON ub.user_id=u.id INNER JOIN book as b ON b.id = ub.book_id WHERE b.id = ? ORDER BY ub.created DESC ";
			pstmt = conn.prepareStatement(sql);
			pstmt.setInt(1, book.getId());
			rs = pstmt.executeQuery();
			while (rs.next()) {
				
				int locationId = 0;
				if (rs.getInt("view_location") != 0) {
					locationId = rs.getInt("view_location");
				} else {
					locationId = rs.getInt("location");
				}
				sql = "SELECT id FROM city WHERE parent_id=" + locationId + " OR id= " + locationId;
				pstmt = conn.prepareStatement(sql);
				rs = pstmt.executeQuery(sql);
				if (rs.next()) {
					sb.append(rs.getInt("id") + ",");
				}
			}
			
		} finally {
			if (rs != null) {
				rs.close();
			}
			if (pstmt != null) {
				pstmt.close();
			}
			if (conn != null) {
				conn.close();
			}
		}
		return sb.toString().endsWith(",") ? sb.toString().substring(0, sb.toString().length()-1) : sb.toString();
	}
}
